home *** CD-ROM | disk | FTP | other *** search
- ; Delay18.asm
- ;
- ; Software/Hardware based Delay Subroutine
-
- .xlist
- include stdlib.a
- includelib stdlib.lib
- .list
-
- ; PPI_B is the I/O address of the keyboard/speaker control
- ; port. This program accesses it simply to introduce a
- ; large number of wait states on faster machines. Since the
- ; PPI (Programmable Peripheral Interface) chip runs at about
- ; the same speed on all PCs, accessing this chip slows most
- ; machines down to within a factor of two of the slower
- ; machines.
-
- PPI_B equ 61h
-
-
- ; RTC is the address of the BIOS timer variable (40:6ch).
- ; The BIOS timer interrupt code increments this 32-bit
- ; location about every 55 ms (1/18.2 seconds). The code
- ; which initializes everything for the Delay routine
- ; reads this location to determine when 1/18th seconds
- ; have passed.
-
- RTC textequ <es:[6ch]>
-
-
-
- dseg segment para public 'data'
-
- ; TimedValue contains the number of iterations the delay
- ; loop must repeat in order to waste 1/18.2 seconds.
-
- TimedValue word 0
-
- ; RTC2 is a dummy variable used by the Delay routine to
- ; simulate accessing a BIOS variable.
-
- RTC2 word 0
-
-
- dseg ends
-
- ;********************************************************
-
-
-
-
-
- cseg segment para public 'code'
- assume cs:cseg, ds:dseg
-
- ; Main program which tests out the DELAY subroutine.
-
- Main proc
- mov ax, dseg
- mov ds, ax
-
- print
- byte "Delay test routine",cr,lf,0
-
- ; Okay, let's see how long it takes to count down 1/18th
- ; of a second. First, point ES as segment 40h in memory.
- ; The BIOS variables are all in segment 40h.
- ;
- ; This code begins by reading the memory timer variable
- ; and waiting until it changes. Once it changes we can
- ; begin timing until the next change occurs. That will
- ; give us 1/18.2 seconds. We cannot start timing right
- ; away because we might be in the middle of a 1/18.2
- ; second period.
-
- mov ax, 40h
- mov es, ax
- mov ax, RTC
- RTCMustChange: cmp ax, RTC
- je RTCMustChange
-
- ; Okay, begin timing the number of iterations it takes
- ; for an 18th of a second to pass. Note that this
- ; code must be very similar to the code in the Delay
- ; routine.
-
- mov cx, 0
- mov si, RTC
- mov dx, PPI_B
- align 4
- TimeRTC: mov bx, 50
- align 4
- DelayLp: ;in al, dx ;Slow to hardware speed.
- dec bx
- jne DelayLp
- cmp si, RTC
- loope TimeRTC
-
- neg cx ;CX counted down!
- mov TimedValue, cx ;Save away
-
- mov ax, ds
- mov es, ax
-
- printf
- byte "TimedValue = %d",cr,lf
- byte "Press any key to continue",cr,lf
- byte "This will begin a delay of five seconds",cr,lf,0
- dword TimedValue
-
- getc
-
-
- mov cx, 180
- DelayIt: call Delay18
- loop DelayIt
-
-
-
- Quit: ExitPgm ;DOS macro to quit program.
- Main endp
-
-
-
- ; Delay- This routine delays for approximately 1/18th second.
- ; Presumably, the variable "TimedValue" in DS has been
- ; initialized with an appropriate count down value
- ; before calling this code.
-
- Delay18 proc near
- push ds
- push es
- push ax
- push bx
- push cx
- push dx
- push si
-
- mov ax, dseg
- mov es, ax
- mov ds, ax
-
- ; The following code contains two loops. The inside
- ; nested loop repeats 10 times. The outside loop
- ; repeats the number of times determined to waste
- ; 1/18.2 seconds. This loop accesses the hardware
- ; port "PPI_B" in order to introduce many wait states
- ; on the faster processors. This helps even out the
- ; timings on very fast machines by slowing them down.
- ; Note that accessing PPI_B is only done to introduce
- ; these wait states, the data read is of no interest
- ; to this code.
-
- mov cx, TimedValue
- mov si, es:RTC2
- mov dx, PPI_B
-
- align 4
- TimeRTC: mov bx, 50
- align 4
- DelayLp: ;in al, dx
- dec bx
- jne DelayLp
- cmp si, es:RTC2
- loope TimeRTC
-
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- pop es
- pop ds
- ret
- Delay18 endp
-
-
-
-
- cseg ends
-
-
-
- sseg segment para stack 'stack'
- stk dw 1024 dup (0)
- sseg ends
- end Main
-